#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    // 1、创建套接字
    int list_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (list_socket < 0)
    {
        cerr << "create list_socket fail!" << endl;
        exit(1);
    }

    // 2、绑定
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(8080);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(list_socket, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        cerr << "bind list_socket fail!" << endl;
        exit(2);
    }

    // 3、设置监听状态
    if (listen(list_socket, 5) < 0)
    {
        cerr << "listen fail!" << endl;
        exit(3);
    }

    // 4、启动服务器
    struct sockaddr peer;
    memset(&peer, 0, sizeof(peer));
    socklen_t len = sizeof(peer);
    for (;;)
    {
        // 获取新连接
        int sock = accept(list_socket, (struct sockaddr *)&peer, &len);
        if (sock < 0)
        {
            cerr << "accept sock fail!" << endl;
            continue; // 继续获取
        }

        // 让子进程执行
        if (fork() == 0)
        {
            close(list_socket);
            // 继续让孙子进程去接受请求
            if (fork() > 0)
            {
                exit(0);
            }
            char buffer[1024];
            recv(sock, buffer, sizeof(buffer), 0); // 阻塞式读取
            std::cout << "-------------------------- http request begin ----------------------------\n"
                      << endl;
            std::cout << buffer << endl;
            std::cout << "--------------------------  http request end ------------------------------\n"
                      << endl;

            // 发送响应
#define FILE "./index.html"
            ifstream is(FILE);
            if (is.is_open())
            {
                is.seekg(0, is.end);
                int len = is.tellg();
                is.seekg(0, is.beg);
                char *file = new char[len + 1];
                is.read(file, len);
                is.close();

                // 构建http响应报头
                string status_line = "http/1.1 307 Temporary Redirect\n";
                string response_header = "Content-Length:" + to_string(len) + "\n";
                response_header += "Set-Cookie:hello HTTP,See you\n";
                string blank = "\n";
                string response_text = file;
                string response = status_line + response_header + blank + response_text;

                // 发送响应报文
                send(sock, response.c_str(), response.size(), 0);
                delete[] file;
            }
            close(sock);
            exit(0);
        }
        // 父进程
        close(sock);
        // 等待子进程回收
        waitpid(-1, nullptr, 0);
    }
    return 0;
}